/***********************************************
 * Symbol Tabel is Coupled with Syntax Tree!!! *
 ***********************************************/

#define SEMANTIC

#ifndef TREE

#include "tree.h"

#endif

#define SYMBOL_FILL_DONE 0
#define SYMBOL_ALREADY_DECLARED 1
#define FUNCTION_ALREADY_DEFINED 2
#define FIELD_ALREADY_DECLARED 3
#define DUPLICATED_STRUCT_NAME 4
#define STRUCTTURE_NAME 5


#define MAX_SYMBOL_COUNT 256

typedef struct SYMBOL_ Symbol;

typedef struct TYPE_ Type;
typedef struct FIELD_ Field;
typedef struct ARGUMENT_ Argument;
typedef struct SNODE_ SNode;

#define SybExtdef 2
#define SybExtDecList 3
#define SybSpecifier 4
#define SybStructSpecifier 5
#define SybOptTag 6
#define SybTag 7
#define SybVarDec 8
#define SybFunDec 9
#define SybVarList 10
#define SybParamDec 11
#define SybCompSt 12
#define SybStmtList 13
#define SybStmt 14
#define SybDefList 15
#define SybDef 16
#define SybDecList 17
#define SybDec 18
#define SybExp 19
#define SybArgs 20
#define SybSEMI 21
#define SybTYPE 23
#define SybID 27
#define SybLB 28
#define SybLP 30
#define SybRETURN 32
#define SybIF 33
#define SybWHILE 35
#define SybASSIGNOP 36
#define SybDIV 37
#define SybAND 38
#define SybOR 39
#define SybRELOP 40
#define SybPLUS 41
#define SybMINUS 42
#define SybSTAR 43
#define SybNOT 44
#define SybDOT 45
#define SybINT 46
#define SybFLOAT 47

#define BASIC_INT 0
#define BASIC_FLOAT 1

#define NAMEVAL 0
#define CONSTANTINT 1
#define CONSTANTFLOAT 2
#define BASICTYPE 3
#define ARRAYTYPE 4
#define ARGUMTYPE 5
#define DATATYPE 6

struct SNODE_ {
    char* name;
    Type* type;
    Type* lastType; // type of last dimend of array /* non-user */
    SNode* pa;
    SNode* ch[32];
    SNode* nexDec;
    SNode* nexPar;
    SNode* nexField;
    int fieldErr;
    int lineno;
};

struct SYMBOL_ {
    char* name;
    Type* type;
    SNode* args;
    int address; /* non-use now */
    int depth; /* scope depth */ /* non-use */
    Symbol* nexs; /* next symbol with same name */ /* non-use */
};

struct TYPE_ {
    enum {
        BASIC,
        ARRAY,
        STRUCTTURE,
        FUNC_BASIC,
        FUNC_STRUCT, /* non-use */
        UNDEFINED
    } kind;

    union {
        int intval;
        float floatval;
    } constant;

    union {
        int basic;
        
        struct {
            Type* type; // element type 
            int size; // array size
        } array;

        struct {
            SNode* field; // field list
            int count; // field count
        } struc;

        struct { /* non-use */
            Type* type;
            Argument* argument; // argument list
            int count; // argument count
        } func;
    } info;
    
};

/* non-use */
struct FIELD_ {
    char *name; // field name
    Type type; // field type
    Field* nexf; // next field
};

/* non-use */
struct ARGUMENT_ {
    char *name;  // argument name
    Type type; // argument type
    Argument* nexa; // next argument
};


/* main process of semantic analysis */
void semanticAnalysis(Node* root);
/* increase depth when match {, decrease depth when macth } */
/* insert symbol at begin, and delete symbol at end */
/* check the symbol table list of the specified name */


/* error reporter */
void serror(int type, int lineno, char *msg, char* sym);


/* printer */
void showSymbols(char* sybs[], int cnt);
void showSymblos();
void showSymbol(int index);
void println();
void showStructField(char* name);
void showArrayType(Type* type);
void showArgs(SNode* arg);


/* symbol table crater */
SNode* getAllSymbol(Node* node);
void insertSymbol(char* symbol);
void getUnqSymbol();
void sortSymbols();
int cmp(const void *s1, const void *s2);


/* symbol table searcher */
int getSymbolIndex(char* name);


/* symbol table filler */
void fillError(int status, SNode* snode);

void fillSymbols(SNode* specifier, SNode* extdeclist);
int fillSymbol(char* name, Type* type, int address);

void fillStructSymbols(SNode* specifier, SNode* extdeclist);
void fillStruct(SNode* snode);

void fillFunctions(SNode* specifier, SNode* func);
int fillFunction(SNode* specifier, SNode* func);


/* assigner */
void typeAssign(SNode* specifier, SNode* var);
void synAssign(SNode* pa, SNode* ch, int type);
void lexAssign(SNode* snode, Node* node, int type);
void udfAssign(SNode* snode);
void tabAssign(SNode* snode, int index, int type);
void stuAssign(SNode* snode);


/* optrand checker */
int isOptrandTypeSame(SNode* opt1, SNode* opt2);
int isOperandBasicType(SNode* opt);
int checkBasic(SNode* opt1, SNode* opt2);
int isOperandTypeInt(SNode* opt);
int isLeftHandVar(SNode* opt);


/* structure checker */
int isVarStructure(SNode* snode);
int isFieldDefined(SNode* snode, SNode *field);
int checkField(SNode* opt1, SNode* opt2);


/* function checker */
int checkFuncArgs(int index, SNode* cargs);


/* operator checker */
int isAlgOperator(Node* node);
int isLogOperator(Node* node);
int isAsnOperator(Node* node);






// void Program(Node* node, SNode* snode);
// void ExtdefList(Node* node, SNode* snode);
// void Extdef(Node* node, SNode* snode);
// void ExtDecList(Node* node, SNode* snode);
// void Specifier(Node* node, SNode* snode);
// void StructSpecifier(Node* node, SNode* snode);
// void OptTag(Node* node, SNode* snode);
// void Tag(Node* node, SNode* snode);
// void VarDec(Node* node, SNode* snode);
// void FunDec(Node* node, SNode* snode);
// void VarList(Node* node, SNode* snode);
// void ParamDec(Node* node, SNode* snode);
// void CompSt(Node* node, SNode* snode);
// void StmtList(Node* node, SNode* snode);
// void Stmt(Node* node, SNode* snode);
// void DefList(Node* node, SNode* snode);
// void Def(Node* node, SNode* snode);
// void DecList(Node* node, SNode* snode);
// void Dec(Node* node, SNode* snode);
// void Exp(Node* node, SNode* snode);
// void Args(Node* node, SNode* snode);